﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using DeploymentCopy.Helper;
using GalaSoft.MvvmLight;
using DeploymentCopy.Model;
using GalaSoft.MvvmLight.Command;
using System.Linq;
using Ionic.Zip;

namespace DeploymentCopy.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        private readonly IDataService _dataService;

        public List<KeyValuePair<EnumDeployMode, string>> DeployModes { get; private set; }

        /// <summary>
        /// The <see cref="WelcomeTitle" /> property's name.
        /// </summary>
        public const string WelcomeTitlePropertyName = "WelcomeTitle";

        private string _welcomeTitle = string.Empty;

        private Config _config;

        /// <summary>
        /// Gets the WelcomeTitle property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string WelcomeTitle
        {
            get
            {
                return _welcomeTitle;
            }

            set
            {
                if (_welcomeTitle == value)
                {
                    return;
                }

                _welcomeTitle = value;
                RaisePropertyChanged(WelcomeTitlePropertyName);
            }
        }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel(IDataService dataService)
        {
            DeployModes = new List<KeyValuePair<EnumDeployMode, string>>()
                {
                    new KeyValuePair<EnumDeployMode, string>(EnumDeployMode.Staging, "Staging"),
                    new KeyValuePair<EnumDeployMode, string>(EnumDeployMode.Product, "Product"),
                    new KeyValuePair<EnumDeployMode, string>(EnumDeployMode.None, "None")
                };
            _dataService = dataService;
            //DeployMode = EnumDeployMode.Staging;
            _config = _dataService.LoadConfig();
            //DeployMode = _config.DefaultDeployMode;
            LoadData();
        }

        private List<ZipLog> _listZipLogsFull = null;

        public const string ListZipLogsFillterPropertyName = "ListZipLogsFillter";
        private List<ZipLog> _listZipLogsFillter = null;
        public List<ZipLog> ListZipLogsFillter
        {
            get
            {
                return _listZipLogsFillter;
            }
            set
            {
                if (_listZipLogsFillter == value)
                {
                    return;
                }

                RaisePropertyChanging(ListZipLogsFillterPropertyName);
                _listZipLogsFillter = value;
                RaisePropertyChanged(ListZipLogsFillterPropertyName);
            }
        }

        public const string DeployModePropertyName = "DeployMode";
        private EnumDeployMode _deployMode = EnumDeployMode.None;
        public EnumDeployMode DeployMode
        {
            get
            {
                return _deployMode;
            }
            set
            {
                if (_deployMode == value)
                {
                    return;
                }

                RaisePropertyChanging(DeployModePropertyName);
                _deployMode = value;
                RaisePropertyChanged(DeployModePropertyName);
                Filter(value);
            }
        }

        private void Filter(EnumDeployMode mode)
        {
            if (mode == EnumDeployMode.Staging)
            {
                ListZipLogsFillter = _listZipLogsFull.Where(n => !n.WasDeployedStaging && !n.IgnoredStaging).ToList();
                ShowSelectStaging = Visibility.Visible;
                ShowSelectProduct = Visibility.Hidden;
            }
            else if (mode == EnumDeployMode.Product)
            {
                ListZipLogsFillter =
                    _listZipLogsFull.Where(
                        n =>
                        !n.WasDeployedProduct && !n.IgnoredProduct && (n.WasDeployedStaging || n.IgnoredStaging)).
                        ToList();
                ShowSelectProduct = Visibility.Visible;
                ShowSelectStaging = Visibility.Hidden;
            }
            else if (mode == EnumDeployMode.None)
            {
                ListZipLogsFillter = _listZipLogsFull;
                ShowSelectProduct = Visibility.Hidden;
                ShowSelectStaging = Visibility.Hidden;
            }
        }
        
        private ZipLog _selectedZipLog = null;
        public ZipLog SelectedZipLog
        {
            get
            {
                return _selectedZipLog;
            }
            set
            {
                if (_selectedZipLog == value)
                {
                    return;
                }
                RaisePropertyChanging("SelectedZipLog");
                _selectedZipLog = value;
                RaisePropertyChanged("SelectedZipLog");
            }
        }

        public const string ShowSelectStagingPropertyName = "ShowSelectStaging";
        private Visibility _showSelectStaging = Visibility.Hidden;
        public Visibility ShowSelectStaging
        {
            get
            {
                return _showSelectStaging;
            }

            set
            {
                if (_showSelectStaging == value)
                {
                    return;
                }

                RaisePropertyChanging(ShowSelectStagingPropertyName);
                _showSelectStaging = value;
                RaisePropertyChanged(ShowSelectStagingPropertyName);
            }
        }

        public const string ShowSelectProductPropertyName = "ShowSelectProduct";
        private Visibility _showSelectProduct = Visibility.Hidden;
        public Visibility ShowSelectProduct
        {
            get
            {
                return _showSelectProduct;
            }

            set
            {
                if (_showSelectProduct == value)
                {
                    return;
                }

                RaisePropertyChanging(ShowSelectProductPropertyName);
                _showSelectProduct = value;
                RaisePropertyChanged(ShowSelectProductPropertyName);
            }
        }

        private RelayCommand _loadCommand;
        public RelayCommand LoadCommand
        {
            get
            {
                return _loadCommand
                    ?? (_loadCommand = new RelayCommand(LoadData));
            }
        }

        private void LoadData()
        {
            _dataService.GetZipLogData(_config,
                                       (item, error) =>
                                           {
                                               if (error != null)
                                               {
                                                   return;
                                               }
                                               _listZipLogsFull = item;
                                               DeployMode = _config.DefaultDeployMode;
                                               SelectedZipLog = null;
                                           });
        }

        private RelayCommand _loadConfigCommand;
        public RelayCommand LoadConfigCommand
        {
            get
            {
                return _loadConfigCommand
                    ?? (_loadConfigCommand = new RelayCommand(LoadConfig));
            }
        }

        private void LoadConfig()
        {
            _config = _dataService.LoadConfig();
        }

        private RelayCommand _deployCommand;
        public RelayCommand Deploycommand
        {
            get
            {
                return _deployCommand
                    ?? (_deployCommand = new RelayCommand(Deploy));
            }
        }

        private void Deploy()
        {
            switch (DeployMode)
            {
                case EnumDeployMode.Staging:
                    DeployStaging();
                    break;
                case EnumDeployMode.Product:
                    DeployProduct();
                    DeployMode = EnumDeployMode.Staging;
                    break;
            }
        }

        private void DeployStaging()
        {
            var deployItems = ListZipLogsFillter.Where(n => n.IsDeployedStaging).ToArray();
            var notDeployItem = ListZipLogsFillter.Where(n => !n.IsDeployedStaging).ToArray();
            
            if (deployItems.Length > 0)
            {
                if (notDeployItem.Length > 0)
                {
                    if (deployItems.Max(n => n.DateName) > notDeployItem.Min(n => n.DateName))
                    {
                        MessageBox.Show("Invalid action.");
                        return;
                    }
                }
            }
            else
            {
                return;
            }

            string folder;
            string tmp;
            ZipEntry[] arr;
            foreach (var item in deployItems)
            {
                using (ZipFile zip = ZipFile.Read(Path.Combine(_config.LookupDirectory, item.Folder, item.FileName)))
                {
                    arr = zip.Entries.ToArray();
                    foreach (var ze in arr)
                    {
                        tmp = ze.FileName;
                        folder = ze.FileName.Split('/')[0].ToLower();
                        ze.FileName = ze.FileName.Substring(ze.FileName.IndexOf("/") + 1);
                        ze.Extract(_config.FolderPaths[folder].Staging, ExtractExistingFileAction.OverwriteSilently);
                        ze.FileName = tmp;
                    }
                }
                item.WasDeployedStaging = true;
                item.IsDeployedStaging = false;
                _dataService.SaveZipLogData();
            }
            DeployMode = EnumDeployMode.Staging;
            Filter(DeployMode);
        }

        private void DeployProduct()
        {
            var deployItems = ListZipLogsFillter.Where(n => n.IsDeployedProduct).ToArray();
            var notDeployItem = ListZipLogsFillter.Where(n => !n.IsDeployedProduct).ToArray();

            if (deployItems.Length > 0)
            {
                if (notDeployItem.Length > 0)
                {
                    if (deployItems.Max(n => n.DateName) > notDeployItem.Min(n => n.DateName))
                    {
                        MessageBox.Show("Invalid action.");
                        return;
                    }
                }
            }
            else
            {
                return;
            }

            string folder;
            string tmp;
            ZipEntry[] arr;
            foreach (var item in deployItems)
            {
                using (ZipFile zip = ZipFile.Read(Path.Combine(_config.LookupDirectory, item.Folder, item.FileName)))
                {
                    arr = zip.Entries.ToArray();
                    foreach (var ze in arr)
                    {
                        tmp = ze.FileName;
                        folder = ze.FileName.Split('/')[0].ToLower();
                        ze.FileName = ze.FileName.Substring(ze.FileName.IndexOf("/") + 1);
                        ze.Extract(_config.FolderPaths[folder].Product, ExtractExistingFileAction.OverwriteSilently);
                        ze.FileName = tmp;
                    }
                }
                item.WasDeployedProduct = true;
                item.IsDeployedProduct = false;
                _dataService.SaveZipLogData();
            }
            DeployMode = EnumDeployMode.Product;
            Filter(DeployMode);
        }

        private RelayCommand _selectAllCommand;
        public RelayCommand SelectAllCommand
        {
            get
            {
                return _selectAllCommand
                    ?? (_selectAllCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (DeployMode == EnumDeployMode.Staging)
                                              {
                                                  foreach (var item in ListZipLogsFillter)
                                                  {
                                                      item.IsDeployedStaging = true;
                                                  }
                                              }
                                              else if (DeployMode == EnumDeployMode.Product)
                                              {
                                                  foreach (var item in ListZipLogsFillter)
                                                  {
                                                      item.IsDeployedProduct = true;
                                                  }
                                              }
                                          }));
            }
        }

        private RelayCommand _noneCommand;
        public RelayCommand NoneCommand
        {
            get
            {
                return _noneCommand
                    ?? (_noneCommand = new RelayCommand(
                                          () =>
                                          {
                                              foreach (var zipLog in _listZipLogsFull)
                                              {
                                                  zipLog.IsDeployedStaging = zipLog.IsDeployedProduct = false;
                                              }
                                          }));
            }
        }

        ////public override void Cleanup()
        ////{
        ////    // Clean up if needed

        ////    base.Cleanup();
        ////}
    }
}